package com.tanger.pay.wechat;

import lombok.Data;

/**
 * @Description 支付参数构造
 * @Author Hchenbin
 * @Date 2024-01-04 17:13
 * @Version 1.0
 */
@Data
public class WeChatPay {
    /**
     * 必填字段
     */
    private String appId;//微信分配的公众账号ID（企业号corpid即为此appId）
    private String mchId;//微信支付分配的商户号
    private String nonceStr;//随机字符串，不长于32位。推荐随机数生成算法
    private String sign;//签名，详见签名生成算法
    private String body;//商品简单描述，该字段须严格按照规范传递，具体请见参数规定
    private String outTradeNo;//商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
    private String totalFee;//订单总金额，单位为分，详见支付金额
    private String spbillCreateIp;//必须传正确的用户端IP,支持ipv4、ipv6格式，获取方式详见获取用户ip指引
    private String notifyUrl;//接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
    private String tradeType;//H5支付的交易类型为MWEB
    /**
     * 特定必填字段
     */
    private String productId;//trade_type=NATIVE，此参数必传。此id为二维码中包含的商品ID，商户自行定义。
    private String openId;//trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识。
    private String sceneInfo;//该字段用于上报支付的场景信息,针对H5支付有以下三种场景,请根据对应场景上报,H5支付不建议在APP端使用，针对场景1，2请接入APP支付，不然可能会出现兼容性问题

    /**
     * 非必填字段
     */
    private String deviceInfo;//终端设备号(门店号或收银设备ID)，注意：PC网页或公众号内支付请传"WEB"
    private String signType;//签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
    private String detail;//单品优惠字段(暂未上线)
    private String attach;//附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
    private String feeType;//符合ISO 4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
    private String timeStart;//订单生成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
    private String timeExpire;//订单失效时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则。注意：最短失效时间间隔必须大于5分钟
    private String goodsTag;//商品标记，代金券或立减优惠功能的参数，说明详见代金券或立减优惠
    private String limitPay;//no_credit--指定不能使用信用卡支付
    private String receipt;//Y，传入Y时，支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能，传此字段才可生效

    private WeChatPay(Builder builder) {
        this.appId = builder.appId;
        this.mchId = builder.mchId;
        this.nonceStr = builder.nonceStr;
        this.sign = builder.sign;
        this.body = builder.body;
        this.outTradeNo = builder.outTradeNo;
        this.totalFee = builder.totalFee;
        this.spbillCreateIp = builder.spbillCreateIp;
        this.notifyUrl = builder.notifyUrl;
        this.tradeType = builder.tradeType;
        this.productId = builder.productId;
        this.openId = builder.openId;
        this.sceneInfo = builder.sceneInfo;
        this.deviceInfo = builder.deviceInfo;
        this.signType = builder.signType;
        this.detail = builder.detail;
        this.attach = builder.attach;
        this.feeType = builder.feeType;
        this.timeStart = builder.timeStart;
        this.timeExpire = builder.timeExpire;
        this.goodsTag = builder.goodsTag;
        this.limitPay = builder.limitPay;
        this.receipt = builder.receipt;
    }

    /**
     * @Description: 基础构造器
     */
    public static Builder basic() {
        Builder builder = new Builder();
        return builder
                .appId(WeChatPayConfig.appId)
                .mchId(WeChatPayConfig.mchId)
                .notifyUrl(WeChatPayConfig.notifyUrl)
                .nonceStr(WeChatUtil.randomStr());
    }

    /**
     * @Description: app支付构造器
     */
    public static Builder appPay() {
        return basic()
                .tradeType("APP");
    }

    /**
     * @Description: 扫码支付构造器,必须传productId
     */
    public static Builder qrCopePay() {
        return basic()
                .tradeType("NATIVE");
    }

    /**
     * @Description: JS-SDK支付构造器,必须传openId
     */
    public static Builder jsSdkPay() {
        return basic()
                .tradeType("JSAPI");
    }

    /**
     * @Description: 小程序支付构造器,必须传openId
     */
    public static Builder xcxPay() {
        return basic()
                .tradeType("JSAPI")
                .appId(WeChatPayConfig.xcxAppId);
    }


    public static class Builder {
        /**
         * 必填字段
         */
        private String appId;//微信分配的公众账号ID（企业号corpid即为此appId）
        private String mchId;//微信支付分配的商户号
        private String nonceStr;//随机字符串，不长于32位。推荐随机数生成算法
        private String sign;//签名，详见签名生成算法
        private String body;//商品简单描述，该字段须严格按照规范传递，具体请见参数规定
        private String outTradeNo;//商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
        private String totalFee;//订单总金额，单位为分，详见支付金额
        private String spbillCreateIp;//必须传正确的用户端IP,支持ipv4、ipv6格式，获取方式详见获取用户ip指引
        private String notifyUrl;//接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
        private String tradeType;//H5支付的交易类型为MWEB
        /**
         * 特定必填字段
         */
        private String productId;//trade_type=NATIVE，此参数必传。此id为二维码中包含的商品ID，商户自行定义。
        private String openId;//trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识。
        private String sceneInfo;//该字段用于上报支付的场景信息,针对H5支付有以下三种场景,请根据对应场景上报,H5支付不建议在APP端使用，针对场景1，2请接入APP支付，不然可能会出现兼容性问题

        /**
         * 非必填字段
         */
        private String deviceInfo;//终端设备号(门店号或收银设备ID)，注意：PC网页或公众号内支付请传"WEB"
        private String signType;//签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
        private String detail;//单品优惠字段(暂未上线)
        private String attach;//附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
        private String feeType;//符合ISO 4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
        private String timeStart;//订单生成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
        private String timeExpire;//订单失效时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则。注意：最短失效时间间隔必须大于5分钟
        private String goodsTag;//商品标记，代金券或立减优惠功能的参数，说明详见代金券或立减优惠
        private String limitPay;//no_credit--指定不能使用信用卡支付
        private String receipt;//Y，传入Y时，支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能，传此字段才可生效

        public Builder appId(String appId) {
            this.appId = appId;
            return this;
        }

        public Builder mchId(String mchId) {
            this.mchId = mchId;
            return this;
        }

        public Builder notifyUrl(String notifyUrl) {
            this.notifyUrl = notifyUrl;
            return this;
        }

        public Builder nonceStr(String nonceStr) {
            this.nonceStr = nonceStr;
            return this;
        }

        public Builder sign(String sign) {
            this.sign = sign;
            return this;
        }

        public Builder body(String body) {
            this.body = body;
            return this;
        }

        public Builder outTradeNo(String outTradeNo) {
            this.outTradeNo = outTradeNo;
            return this;
        }

        public Builder totalFee(String totalFee) {
            this.totalFee = totalFee;
            return this;
        }

        public Builder spbillCreateIp(String spbillCreateIp) {
            this.spbillCreateIp = spbillCreateIp;
            return this;
        }

        public Builder tradeType(String tradeType) {
            this.tradeType = tradeType;
            return this;
        }

        public Builder productId(String productId) {
            this.productId = productId;
            return this;
        }

        public Builder openId(String openId) {
            this.openId = openId;
            return this;
        }

        public Builder sceneInfo(String sceneInfo) {
            this.sceneInfo = sceneInfo;
            return this;
        }

        public Builder deviceInfo(String deviceInfo) {
            this.deviceInfo = deviceInfo;
            return this;
        }

        public Builder signType(String signType) {
            this.signType = signType;
            return this;
        }

        public Builder detail(String detail) {
            this.detail = detail;
            return this;
        }

        public Builder attach(String attach) {
            this.attach = attach;
            return this;
        }

        public Builder feeType(String feeType) {
            this.feeType = feeType;
            return this;
        }

        public Builder timeStart(String timeStart) {
            this.timeStart = timeStart;
            return this;
        }

        public Builder timeExpire(String timeExpire) {
            this.timeExpire = timeExpire;
            return this;
        }

        public Builder goodsTag(String goodsTag) {
            this.goodsTag = goodsTag;
            return this;
        }

        public Builder limitPay(String limitPay) {
            this.limitPay = limitPay;
            return this;
        }

        public Builder receipt(String receipt) {
            this.receipt = receipt;
            return this;
        }

        public WeChatPay build() {
            return new WeChatPay(this);
        }
    }


}
